package cn.turboinfo.fuyang.api.domain.mini.helper;


import cn.turboinfo.fuyang.api.domain.common.service.category.CategoryService;
import cn.turboinfo.fuyang.api.domain.common.service.contract.ContractTmplService;
import cn.turboinfo.fuyang.api.domain.common.service.file.FileAttachmentService;
import cn.turboinfo.fuyang.api.domain.common.service.product.ProductService;
import cn.turboinfo.fuyang.api.domain.util.TemplateUtils;
import cn.turboinfo.fuyang.api.domain.web.component.file.FileAttachmentHelper;
import cn.turboinfo.fuyang.api.domain.web.component.file.FileRefTypeConstant;
import cn.turboinfo.fuyang.api.entity.common.pojo.category.Category;
import cn.turboinfo.fuyang.api.entity.common.pojo.contract.ContractTmpl;
import cn.turboinfo.fuyang.api.entity.common.pojo.file.FileAttachment;
import cn.turboinfo.fuyang.api.entity.common.pojo.order.ServiceOrder;
import cn.turboinfo.fuyang.api.entity.common.pojo.product.Product;
import com.aspose.words.Document;
import com.aspose.words.ImageSaveOptions;
import com.aspose.words.PageSet;
import com.aspose.words.SaveFormat;
import lombok.RequiredArgsConstructor;
import org.apache.commons.io.IOUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@RequiredArgsConstructor
@Component
public class ContractHelper {

    private final FileAttachmentService fileAttachmentService;

    private final CategoryService categoryService;

    private final ContractTmplService contractTmplService;

    private final ProductService productService;

    private final FileAttachmentHelper fileAttachmentHelper;

    public void generateContractPDF(ContractTmpl contractTmpl, Map<String, Object> mappingValueMap, OutputStream os) {

        // 模版文件
        FileAttachment fileAttachment = fileAttachmentService.findByRefIdAndRefType(contractTmpl.getId(), FileRefTypeConstant.CONTRACT_TMPL_FILE)
                .stream()
                .findFirst()
                .orElseThrow();
        File tmplFile = fileAttachmentHelper.readFileAttachment(fileAttachment);

        try (InputStream is = new FileInputStream(tmplFile);
             XWPFDocument document = new XWPFDocument(is)) {

            // 先在内存中替换模板
            TemplateUtils.replaceDocxTemplate(document, mappingValueMap);

            ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
            document.write(baos);

            // 生成PDF
            Document convertDocument = new Document(new ByteArrayInputStream(baos.toByteArray()));
            convertDocument.save(os, SaveFormat.PDF);

            IOUtils.copy(is, os);
            os.flush();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public List<String> generateContractImage(ContractTmpl contractTmpl, Map<String, Object> mappingValueMap, Path absolutePath) {
        List<String> imageList = new ArrayList<>();
        // 模版文件
        FileAttachment fileAttachment = fileAttachmentService.findByRefIdAndRefType(contractTmpl.getId(), FileRefTypeConstant.CONTRACT_TMPL_FILE)
                .stream()
                .findFirst()
                .orElseThrow();
        File tmplFile = fileAttachmentHelper.readFileAttachment(fileAttachment);

        try (InputStream is = new FileInputStream(tmplFile);
             XWPFDocument document = new XWPFDocument(is)) {

            // 先在内存中替换模板
            TemplateUtils.replaceDocxTemplate(document, mappingValueMap);

            ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
            document.write(baos);

            // 生成PDF
            Document convertDocument = new Document(new ByteArrayInputStream(baos.toByteArray()));
            ImageSaveOptions iso = new ImageSaveOptions(SaveFormat.JPEG);
            for (var i = 0; i < convertDocument.getPageCount(); i++) {
                iso.setPageSet(new PageSet(i));
                String fileName = UUID.randomUUID() + ".jpeg";
                FileOutputStream os = new FileOutputStream(absolutePath.resolve(fileName).toFile());
                //doc文件保存成图片至本地
                convertDocument.save(os, iso);
                os.flush();
                imageList.add(fileName);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return imageList;
    }

    public ContractTmpl getContractTmpl(List<ContractTmpl> contractTmplList, ServiceOrder serviceOrder) {
        ContractTmpl contractTmpl;
        // 先过滤当前分类下是否有模版
        contractTmpl = contractTmplList.stream()
                .filter(tmpl -> tmpl.getCategoryId().equals(serviceOrder.getCategoryId()))
                .findFirst()
                .orElse(null);
        // 当前分类下没有模版则查询父级分类下是否有模版
        if (contractTmpl == null) {
            Category category = categoryService.getByIdEnsure(serviceOrder.getCategoryId());
            contractTmpl = contractTmplList.stream()
                    .filter(tmpl -> tmpl.getCategoryId().equals(category.getParentId()))
                    .findFirst()
                    .orElse(null);
        }
        // 父级分类下没有模版则使用默认模版
        if (contractTmpl == null) {
            contractTmpl = contractTmplList.stream()
                    .filter(tmpl -> tmpl.getCategoryId().equals(0L))
                    .findFirst()
                    .orElse(null);
        }
        return contractTmpl;
    }

    public ContractTmpl getContractTmpl(ServiceOrder serviceOrder) {
        ContractTmpl contractTmpl;

        // 产品产品是否需要合同
        Product product = productService.getByIdEnsure(serviceOrder.getProductId());
        contractTmpl = contractTmplService.getById(product.getContractTmplId()).orElse(null);
        if (contractTmpl != null) {
            return contractTmpl;
        }

        List<ContractTmpl> companyTmplList = contractTmplService.findByCompanyId(serviceOrder.getCompanyId());


        // 如果企业没有模版，则使用默认模版
        contractTmpl = getContractTmpl(companyTmplList, serviceOrder);
        if (contractTmpl == null) {
            List<ContractTmpl> sysTmplList = contractTmplService.findByCompanyId(0L);
            contractTmpl = getContractTmpl(sysTmplList, serviceOrder);
        }
        return contractTmpl;

    }

    public boolean hasContractTmpl(ServiceOrder serviceOrder) {

        return getContractTmpl(serviceOrder) != null;
    }

}
